package com.zkthink.ceres.tenant.service.impl;

import static com.zkthink.ceres.common.constant.CacheKey.TENANT;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil;
import com.zkthink.base.service.SuperCacheServiceImpl;
import com.zkthink.ceres.authority.entity.auth.User;
import com.zkthink.ceres.authority.service.auth.UserService;
import com.zkthink.ceres.cms.entity.CmsTemplate;
import com.zkthink.ceres.cms.service.CmsTemplateService;
import com.zkthink.ceres.common.constant.BizConstant;
import com.zkthink.ceres.common.event.TenantCreatedEvent;
import com.zkthink.ceres.store.entity.Store;
import com.zkthink.ceres.store.service.StoreService;
import com.zkthink.ceres.tenant.dao.TenantMapper;
import com.zkthink.ceres.tenant.dto.TenantSaveDTO;
import com.zkthink.ceres.tenant.dto.TenantUpdateDTO;
import com.zkthink.ceres.tenant.entity.Tenant;
import com.zkthink.ceres.tenant.enumeration.TenantStatusEnum;
import com.zkthink.ceres.tenant.enumeration.TenantTypeEnum;
import com.zkthink.ceres.tenant.service.TenantService;
import com.zkthink.ceres.tenant.strategy.InitSystemContext;
import com.zkthink.database.mybatis.conditions.Wraps;
import com.zkthink.exception.BizException;
import com.zkthink.utils.BeanPlusUtil;
import com.zkthink.utils.StrHelper;
import io.jsonwebtoken.lang.Collections;
import java.util.List;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * <p>
 * 业务实现类 企业
 * </p>
 *
 * @author ceres
 * @date 2019-10-24
 */
@Slf4j
@Service
public class TenantServiceImpl extends SuperCacheServiceImpl<TenantMapper, Tenant> implements
    TenantService {

  @Autowired
  private InitSystemContext initSystemContext;

  @Autowired
  private UserService userService;

  @Autowired
  private StoreService storeService;

  @Autowired
  private CmsTemplateService cmsTemplateService;

  @Autowired
  private ApplicationEventPublisher publisher;


  @Override
  protected String getRegion() {
    return TENANT;
  }

  @Override
  public Tenant getByCode(String tenant) {
    return super.getOne(Wraps.<Tenant>lbQ().eq(Tenant::getCode, tenant));
  }

  @Override
  @Transactional(rollbackFor = Exception.class)
  public Tenant save(TenantSaveDTO data) {
    //查询手机号是否已注册
    if (userService.check(data.getMobile())) {
      throw new BizException("手机号已注册");
    }
    int count = this.count(Wraps.<Tenant>lbQ().eq(Tenant::getName, data.getName()));
    if (count > 0) {
      throw new BizException("商家名称已使用");
    }
    //生成编码
    int code = 10000;
    String lastCode = this.getLastCode();
    if (StrUtil.isNotBlank(lastCode)) {
      code = Integer.parseInt(lastCode) + 1;
    }
    // defaults 库
    data.setCode(String.valueOf(code));
    User user = BeanPlusUtil.toBean(data, User.class);
    user.setAccount(data.getMobile());
    user.setName(StrHelper.getOrDef(data.getName(), data.getMobile()));
    if (StrUtil.isEmpty(user.getPassword())) {
      user.setPassword(BizConstant.DEF_PASSWORD);
    }
    user.setStatus(true);

    // 1， 保存租户 (默认库)
    Tenant tenant = BeanPlusUtil.toBean(data, Tenant.class);
    tenant.setStatus(TenantStatusEnum.NORMAL);
    tenant.setType(TenantTypeEnum.CREATE);
    // defaults 库
    save(tenant);

    try {
      //先睡眠200ms，等商户初始化成功，再调用下面的逻辑
      Thread.sleep(200);
    } catch (Exception e) {
      log.error(e.getMessage(), e);
    }

    //初始化库，表, 数据  考虑异步完成 // 租户库
    initSystemContext.init(tenant.getCode());

    //初始化用户表
    userService.initUser(user);

    //初始化店铺
    initStore(data.getMobile(), data.getName());

    //初始化店铺装修
    initCmsTemplate();

    publisher.publishEvent(TenantCreatedEvent.builder()
        .tenantCode(String.valueOf(code)).build());

    return tenant;
  }

  @Override
  @Transactional(rollbackFor = Exception.class)
  public Tenant update(TenantUpdateDTO data) {

    if (data == null || StringUtils.isBlank(data.getCode())) {
      throw new BizException("参数不正确");
    }

    List<User> userList = userService.getByTenantCode(data.getCode());

    if (Collections.isEmpty(userList)) {
      throw new BizException("商家信息异常，无法更新");
    }

    User user = userService.getByAccount(data.getMobile());
    if (user != null) {
      //说明本次没有修改账号，所以跟原来数据库中的记录相等
      if (user.getId().equals(userList.get(0).getId())) {

      } else {
        throw new BizException("手机号已注册");
      }
    }

    List<Tenant> tenantList = baseMapper.selectList(
        Wraps.<Tenant>lbQ().eq(Tenant::getName, data.getName()).ne(Tenant::getId, data.getId()));
    if (tenantList != null && tenantList.size() > 0) {
      throw new BizException("商家名称已使用");
    }

    //更新 商家信息
    Tenant tenant = baseMapper.selectById(data.getId());
    if (tenant == null) {
      throw new BizException("商家不存在");
    }

    tenant.setAccount(data.getMobile());
    tenant.setName(data.getName());
    tenant.setDuty(data.getDuty());
    tenant.setAddress(data.getAddress());
    tenant.setContactTel(data.getContactTel());
    tenant.setStartTime(data.getStartTime());
    tenant.setExpireLimitYear(data.getExpireLimitYear());
    baseMapper.updateById(tenant);

    Store store = storeService.findByTenantCode(data.getCode());
    if (store != null) {
      store.setStoreName(data.getName());
      store.setMobile(data.getContactTel());
      storeService.updateById(store);
    }

    if (user != null) {
      user.setAccount(data.getMobile());
      user.setName(data.getName());
      userService.updateById(user);
    }

    return tenant;
  }

  @Override
  public boolean check(String tenantCode) {
    return super.count(Wraps.<Tenant>lbQ().eq(Tenant::getCode, tenantCode)) > 0;
  }

  @Override
  @Transactional(rollbackFor = Exception.class)
  public Boolean delete(List<Long> ids) {
    List<String> tenantCodeList = listObjs(
        Wraps.<Tenant>lbQ().select(Tenant::getCode).in(Tenant::getId, ids), Convert::toStr);
    if (tenantCodeList.isEmpty()) {
      return true;
    }
    removeByIds(ids);

    return initSystemContext.delete(tenantCodeList);
  }

  @Override
  public String getLastCode() {
    return baseMapper.getLastCode();
  }

  private void initStore(String mobile, String storeName) {
    storeService.save(Store.builder().mobile(mobile).storeName(storeName).build());
  }

  private void initCmsTemplate() {
    cmsTemplateService.save(CmsTemplate.builder().build());
  }


}
